#ifndef     __MUTEX_H
#define     __MUTEX_H

#include "../rtx/rtx_os.h"
#include "../utils/nocopyable.h"

namespace rtos {

namespace lazy {

class Mutex : private NoCopyable {
public:
    void init(const char *name = "other") {
        osMutexAttr_t attr;
        attr.name = name;
        attr.attr_bits = osMutexRecursive + osMutexRobust + osMutexPrioInherit;
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxMutexCbSize;
        m_id = osMutexNew(&attr);
    }

    inline osStatus_t lock(uint32_t timeout = osWaitForever) {
        return osMutexAcquire(m_id, timeout);
    }

    inline osStatus_t un_lock() {
        return osMutexRelease(m_id);
    }

private:
    osMutexId_t m_id;
    uint64_t m_cb_mem[ (osRtxMutexCbSize + 7) / 8 ];
};

}


class Mutex : private NoCopyable {
public:
    Mutex(const char *name = "other") {
        osMutexAttr_t attr;
        attr.name = name;
        attr.attr_bits = osMutexRecursive + osMutexRobust + osMutexPrioInherit;
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxMutexCbSize;
        m_id = osMutexNew(&attr);
    }

    inline osStatus_t lock(uint32_t timeout = osWaitForever) {
        return osMutexAcquire(m_id, timeout);
    }

    inline osStatus_t un_lock() {
        return osMutexRelease(m_id);
    }

private:
    osMutexId_t m_id;
    uint64_t m_cb_mem[ (osRtxMutexCbSize + 7) / 8 ];
};

struct AutoLock : private NoCopyable {

    inline AutoLock(Mutex &m) : lock(m) {
        m.lock();
    }

    inline ~AutoLock() {
        lock.un_lock();
    }

private:
    Mutex &lock;
};

#define AUTO_LOCK(m)        rtos::AutoLock __(m)

}


#endif
